﻿using System;
using System.Linq.Expressions;
using MoroMoro.Samples.ToDoList.Base.Domain.Specifications;
using MoroMoro.Samples.ToDoList.Base.Domain.Expanders;

namespace MoroMoro.Samples.ToDoList.Domain.ToDos
{
    /// <summary>
    /// <see cref="ToDo"/> の<see cref="ToDo.State">状態</see>を特定の状態に戻せるかどうかを判断します。
    /// </summary>
    [Serializable]
    public sealed class ToDoCanRevertSpecification : Specification<ToDo>
    {
        /// <summary>
        /// <see cref="ToDoCanRevertSpecification"/> クラスの新しいインスタンスを初期化します。
        /// </summary>
        /// <param name="destination">遷移先となる<see cref="ToDo.State">状態</see>。</param>
        public ToDoCanRevertSpecification(ToDoState destination)
        {
            _destination = destination;
        }


        /// <summary>
        /// 遷移先となる<see cref="ToDo.State">状態</see>。
        /// </summary>
        private readonly ToDoState _destination;


        /// <inheritdoc/>
        protected override Expression<Func<ToDo, bool>> CreateExpression()
        {
            switch (_destination)
            {
                case ToDoState.Untouched:
                    return entity => (entity.State == ToDoState.Touched);

                case ToDoState.Touched:
                    return entity => (entity.State == ToDoState.Completed);

                case ToDoState.Completed:
                    return entity => (false);

                default:
                    throw new InvalidOperationException();
            }
        }


        /// <inheritdoc/>
        protected override Expander<ToDo> GetExpander()
        {
            return new Expander<ToDo>(new ToDoStateViewpoint());
        }
    }
}
